<?php

namespace Mlym\CodeGeneration\ControllerGeneration\Method;


use EasySwoole\HttpAnnotation\AnnotationTag\Param;
use EasySwoole\ORM\Utility\Schema\Column;
use Mlym\CodeGeneration\Constant\Validate;
use Mlym\CodeGeneration\ControllerGeneration\ControllerConfig;
use Mlym\CodeGeneration\ControllerGeneration\ControllerGeneration;
use Mlym\CodeGeneration\Middleware\Bean\View\Validate\ValidateBean;
use Mlym\CodeGeneration\Middleware\Bean\View\ViewColumnBean;
use Nette\PhpGenerator\Method;

abstract class MethodAbstract extends \Mlym\CodeGeneration\ClassGeneration\MethodAbstract
{
    /**
     * @var Method $method
     */
    protected $method;
    /**
     * @var ControllerConfig
     */
    protected $controllerConfig;

    protected $methodName = 'methodName';
    protected $methodDescription = '这是生成的测试方法介绍';
    protected $responseParam = [
        'code' => '状态编码',
        'data' => '数据集合',
        'msg' => '提示信息',
    ];
    protected $authParam = null;
    protected $methodAllow = "GET,POST";
    protected $responseSuccessText = '{"code":200,"result":[],"msg":"操作成功"}';
    protected $responseFailText = '{"code":400,"result":[],"msg":"操作失败"}"}';
    protected $ignoreField = ['create_time', 'update_time', 'createAt', 'updateAt', 'createTime', 'updateTime'];

    function __construct(ControllerGeneration $classGeneration)
    {
        $this->classGeneration = $classGeneration;
        $this->method = $classGeneration->getPhpClass()->addMethod($this->getMethodName());
        $this->controllerConfig = $classGeneration->getConfig();
        if ($this->controllerConfig instanceof ControllerConfig) {
            $this->authParam = $this->controllerConfig->getAuthSessionName();
        }
    }

    function run()
    {
        $this->addRequestComment();
        $this->addMethodBody();
        $this->addComment();
    }


    protected function addRequestComment()
    {
        $method = $this->method;
        $methodName = $this->methodName;
        $methodDescription = $this->methodDescription;

        //配置基础注释
        $method->addComment("@Api(name=\"{$methodName}\",path=\"{$this->controllerConfig->getMiddlewareData()->getModule()->getApi()->getPath()}/{$methodName}\")");
        $method->addComment("@ApiDescription(\"{$this->controllerConfig->getMiddlewareData()->getModule()->getComment()},{$methodDescription}\")");
        $method->addComment("@Method(allow={{$this->methodAllow}})");
        if ($this->authParam) {
            $method->addComment("@Param(name=\"{$this->authParam}\", from={COOKIE,HEADER,GET,POST}, alias=\"权限验证token\" required=\"\")");
        }
        $method->addComment("@InjectParamsContext(key=\"param\")");
    }


    protected function getModelName()
    {
        $modelNameArr = (explode('\\', $this->controllerConfig->getModelClass()));
        $modelName = end($modelNameArr);
        return $modelName;
    }


    protected function addColumnComment(Param $param)
    {
        $method = $this->method;
        $commentStr = "@Param(name=\"{$param->name}\"";
        $arr = ['alias', 'description', 'defaultValue',
            'required', 'notEmpty', 'optional',
            'activeUrl', 'alpha', 'alphaNum', 'alphaDash', 'between', 'bool',
            'decimal', 'dateBefore', 'dateAfter', 'equal', 'different',
            'equalWithColumn', 'differentWithColumn', 'lessThanWithColumn', 'greaterThanWithColumn',
            'func', 'inArray', 'notInArray', 'isIp',
            'integer', 'numeric', 'float', 'length', 'lengthMax', 'lengthMin',
            'betweenLen', 'money', 'max', 'min', 'regex', 'allDigital',
            'timestamp', 'timestampBeforeDate', 'timestampAfterDate',
            'timestampBefore', 'timestampAfter', 'url', 'allowFile', 'allowFileType'
        ];

        /**
         * from参数
         */
        if ($param->from) {
            $commentStr .= ", from={" . implode(",", $param->from) . "}";
        }

        /**
         * 验证参数
         */
        foreach ($arr as $value) {
            if ($param->$value !== null) {
                if (is_array($param->$value)) {
                    $commentStr .= ", $value=" . json_encode($param->$value, 512);
                } else {
                    $commentStr .= ", $value=\"{$param->$value}\"";
                }
            }
        }

        $commentStr .= ")";
        $method->addComment($commentStr);
    }

    protected function newColumnParam(Column $column)
    {
        $columnName = $column->getColumnName();
        $columnComment = $column->getColumnComment();
        $paramValue = new Param();
        $paramValue->name = $columnName;
        $paramValue->alias = explode(',', $columnComment)[0];
        $paramValue->description = $columnComment;
        $paramValue->defaultValue = $column->getDefaultValue();
        return $paramValue;
    }

    protected function chunkTableColumn(callable $callback)
    {
        $table = $this->controllerConfig->getTable();
        foreach ($table->getColumns() as $column) {
            $columnName = $column->getColumnName();
            $result = $callback($column, $columnName);
            if ($result === true) {
                break;
            }
        }
    }

    /**
     * 自定义处理schema数据
     * @param callable $callback
     */
    protected function chunkSchemaColumn(callable $callback)
    {
        foreach ($this->controllerConfig->getMiddlewareData()->getView() as $column) {

            /**
             * 这个版本先处理当前模块的字段，下个版本考虑关联模块
             */
            if ($column instanceof ViewColumnBean && $column->getModule() == $this->controllerConfig->getMiddlewareData()->getModule()->getTableName()) {
                $result = $callback($column);
                if ($result === true) {
                    break;
                }
            }
        }
    }

    /**
     * 构建基础Param注解数据
     * @param ViewColumnBean $column
     * @return Param
     */
    protected function buildColumnParam(ViewColumnBean $column): Param
    {
        $columnName = $column->getName();
        $columnDescription = $column->getDescription();
        $paramValue = new Param();
        if ($column->getModule() != $this->controllerConfig->getMiddlewareData()->getModule()->getTableName()) {
            $paramValue->name = $column->getModule() . '_' . $columnName;
        } else {
            $paramValue->name = $columnName;
        }

        $paramValue->alias = explode(',', $columnDescription)[0];
        $paramValue->alias == $columnDescription || $paramValue->description = $columnDescription;
        return $paramValue;
    }

    /**
     * 构建搜索字段Param注解数据
     * @param ViewColumnBean $column
     * @return Param
     */
    protected function buildSearchColumnParam(ViewColumnBean $column): Param
    {
        $paramValue = $this->buildColumnParam($column);
        $paramValue->from = ['GET'];
        $column->getRule() && $paramValue->optional = '';
        return $paramValue;
    }

    /**
     * 构建Param注解数据，主要针对add/edit 方法
     * @param ViewColumnBean $column
     * @return Param
     */
    protected function buildValidateColumnParam(ViewColumnBean $column): Param
    {
        $paramValue = $this->buildColumnParam($column);
        $paramValue->from = ['POST'];
        foreach ($column->getValidate() as $validateBean) {
            if ($validateBean instanceof ValidateBean) {
                $validator = $validateBean->getValidator();
                if ($validateBean->getExtra()->getValue()) {
                    $paramValue->$validator = $validateBean->getExtra()->getValue();
                } else {
                    $paramValue->$validator = '';
                }
            }
        }
        return $paramValue;
    }

    /**
     * 构建where条件
     * @param ViewColumnBean $column
     * @param $methodBody
     */
    protected function buildWhere(ViewColumnBean $column, &$methodBody)
    {
        $columnName = $column->getName();
        if ($this->controllerConfig->getMiddlewareData()->getModule()->getRelation()) {
            $columnName = $this->controllerConfig->getMiddlewareData()->getModule()->getAlias() . "." . $column->getName();
        }
        if ($column->getSearch()) {
            switch ($column->getRule()) {
                case "=":
                case "!=":
                case ">":
                case "<":
                case ">=":
                case "<=":
                case "between":
                    $methodBody .= <<<Body
empty(\$param['{$column->getName()}']) || \$model->where('{$columnName}', \$param['{$column->getName()}'], '{$column->getRule()}');

Body;
                    break;
                case "like":
                    $methodBody .= <<<Body
empty(\$param['{$column->getName()}']) || \$model->where('{$columnName}', '%' . \$param['{$column->getName()}'] . '%', '{$column->getRule()}');

Body;
                    break;
            }
        }
    }

    protected function filterField()
    {

    }

    /**
     * @return string
     */
    public function getMethodName(): string
    {
        return $this->methodName;
    }


}
